/*
 * @Author       : wfl
 * @LastEditors: fj
 * @description  :
 * @updateInfo   :
 * @Date         : 2023-07-26 11:10:34
 * @LastEditTime: 2023-08-10 15:09:52
 */
import { buildUUID, ikMitt, ikNotification, ikStore } from 'iking-utils'
import { ElNotification } from 'element-plus'
import router from '@g/router'
import useUserStore from './user'
import useNotificationStore from './notification'
import useApproveFlowStore from './approveFlow'

export const REDIRECT = {
  // 审批模块跳转
  approve: {
    path: '/approve-center/approve-list',
    value: {
      // 进入 我审批的
      'back-to-approve': 1,
      submit: 1,
      remind: 1,
      // 进入 我提交的
      reject: 2,
      pass: 2,
      'back-to-initiator': 2,
      // 进入 抄送我的
      'carbon-copy': 3
    }
  }
}

const logStyle = 'font-size: 14px; color: green; '
const logErrStyle = 'text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);color: red;'
const useSocketStore = defineStore(
  // 唯一ID
  'socket',
  () => {
    ikNotification.checkPermission()
    // =======================Socket相关================================
    // socket实例
    let socketApp: WebSocket | null = null
    // 初始重连间隔为 1 秒
    let reconnectInterval = 1000
    // 最大重连间隔
    const maxReconnectInterval = import.meta.env.VITE_APP_MAX_SOCKET_RECONNECT_TIME
    // 重连定时器
    let timer: number | null = null
    // 保存消息实例，用于点击后关闭对应实例
    const notificationMap = new Map()
    const userStore = useUserStore()
    const flowStore = useApproveFlowStore()
    const notificationStore = useNotificationStore()
    // 是否连接
    const connected = ref(false)
    // 系统消息
    const systemMsgList = ref<any[]>([])
    // 消息地址
    const SOCKET_URL = `ws://${location.host}${import.meta.env.VITE_APP_SOCKET_URL}/server/ws/message`
    // =======================Socket相关================================
    const linkTo = (path: string, info: { tabId?: string; id?: string; target?: '_black' | '_self'; uuid?: string; }) => {
      if (path.startsWith('http')) {
        window.open(path, info.target)
      }
      else {
        flowStore.setSocketInfo({
          path,
          ...info
        })
        router.push({
          path
        })
      }

      if (notificationMap.has(info?.uuid)) {
        notificationMap.get(info?.uuid)?.close()
        notificationMap.delete(info?.uuid)
      }
    }
    // 创建socket
    const createSocket = () => {
      const user = userStore.userInfo
      if (!user)
        return
      socketApp = new WebSocket(`${SOCKET_URL}?userId=${user?.id}&token=${ikStore.local.getItem('token')}`)
      // 连接成功
      socketApp.onopen = () => {
        console.info('%c[Iking Admin] Socket已连接', logStyle)
        reconnectInterval = 1000 // 重连成功后重置重连间隔
      }
      // 收到消息
      socketApp.onmessage = (e: any) => {
        console.info(`%c[Iking Admin] Socket消息： ${e?.data}`, logStyle)
        try {
          const data = JSON.parse(e?.data)
          const { redirectTo, text, showNotification }: { redirectTo: Array<{ redirectLink: string; redirectName: string; }>; text: string; showNotification: Boolean; } = data
          const linkArr: any[] = []
          // 不需要系统提示的消息
          if (!showNotification) {
            ikMitt.emit('socket-message', e)
            return
          }
          const uuid = buildUUID()
          if (Array.isArray(redirectTo)) {
            for (const li of redirectTo) {
              const isHttpLink = li?.redirectLink.startsWith('http')
              if (isHttpLink) {
                linkArr.push(h('a', { class: 'ik-sys-msg-no', onClick: () => linkTo(li?.redirectLink, { uuid, target: '_black' }) }, li?.redirectName || '查看详情'))
              }
              else {
                const splitPath = li?.redirectLink.split('/')
                const tabId = splitPath?.[2]
                const id = splitPath?.[3]
                let redirectObj: any
                if (li?.redirectLink.startsWith('approve://'))
                  redirectObj = REDIRECT.approve
                linkArr.push(h('a', {
                  class: 'ik-sys-msg-no',
                  onClick: () => redirectObj
                    ? linkTo(redirectObj.path, { tabId: redirectObj.value[tabId], id, uuid, target: '_self' })
                    : (() => {
                        router.push({
                          path: li.redirectLink,
                          query: {
                            link: li.redirectLink
                          }
                        })
                        // 跳转后关闭消息框
                        if (notificationMap.has(uuid)) {
                          notificationMap.get(uuid)?.close()
                          notificationMap.delete(uuid)
                        }
                      })()
                }, li?.redirectName || '查看详情'))
              }
            }
          }
          // 顶部消息图表 - 未读消息数+1
          notificationStore.message += 1
          const infoHtml = []
          for (const i of text?.split('\r\n'))
            infoHtml.push(h('p', { class: '' }, i))

          const Notifion = ElNotification({
            title: '有新消息',
            // dangerouslyUseHTMLString: true,
            type: 'success',
            duration: 0,
            message: h('p', {
              style: ''
            },
            [...infoHtml, ...linkArr]
            )
          })
          notificationMap.set(uuid, Notifion)
        }
        catch (error) {
        }
        try {
          ikMitt.emit('socket-message', e)
          const data = JSON.parse(e?.data)
          systemMsgList.value.push(data)
          ikNotification.showNotification({
            title: '有新消息',
            message: e?.data
          }, () => { })
        }
        catch (error) {

        }
      }
      // 连接错误
      socketApp.onerror = () => {
        console.error('%c[Iking Admin] Socket连接错误', logErrStyle)
      }
      // 连接关闭
      socketApp.onclose = (e: any) => {
        console.info('%c[Iking Admin] Socket连接关闭', logStyle, e)
        timer && clearTimeout(timer)
        // 根据需要判断是否进行重连
        const isLoginPage = location.href.includes('/login')
        if (!e.wasClean && !isLoginPage)
          reconnect()
      }
      return socketApp
    }
    // 重连
    const reconnect = () => {
      if (socketApp)
        socketApp.close()
      // 指数退避重连时间逐步增加
      timer = window.setTimeout(() => {
        if (reconnectInterval < maxReconnectInterval)
          reconnectInterval *= 2 // 重连间隔翻倍

        console.info(`%c[Iking Admin] 下次重连时间${reconnectInterval}ms后`, logStyle)
        createSocket()
      }, reconnectInterval)
    }
    // 页面加载完成后创建socket
    window.onload = () => {
      createSocket()
    }

    // 发送消息
    const emitMessage = (data?: string) => {
      socketApp?.send(JSON.stringify({ data }))
    }

    // 关闭socket
    const closeScoket = () => {
      socketApp?.close()
    }

    return {
      connected,
      systemMsgList,
      createSocket,
      closeScoket,
      emitMessage
    }
  }
)

export default useSocketStore
